package common.customType;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.UserType;

import common.StringUtils;
import common._ArrayList;
import common._List;

public class SimpleListType extends _ArrayList implements UserType, Serializable {

	/* 有几个字段就有几个值，这里容易出错，要多注意 */
	private static final int[] SQL_TYPES = { Types.VARCHAR };

	/* 这个方法告诉Hibernate在成生DDL时对列采用什么样的SQL语法 */
	public int[] sqlTypes() {
		return SQL_TYPES;
	}

	/*
	 * Hibernate返回什么样的映射类型，与 <property name="address" type="model.AddressType">
	 * 指定的类一致。事实上也可以把AddressType拆分为两个类，一个类是只携带信息的JavaBean，它里面
	 * 没有逻辑操作也没有实现UserType（比如AddressBean）；而另一个类实现了UserType，它所面对的就不是现在这个
	 * AddressType类的homeAddr和homeAddr属性，它面对的是AddressBean。在本例中为了简洁方便，只用了一个类。
	 */
	public Class returnedClass() {
		return SimpleListType.class;
	}

	/*
	 * 表明这个类的实例在创建以后就不可以改变属性。Hibernate能为不可改变的类作一些性能优化。
	 */
	public boolean isMutable() {
		return false;
	}

	/*
	 * 由于AddressType是不可变的，所以深拷贝可以直接返回对象引用。拷贝的对象由应用程序使用， 而原版对象由Hibernate维护以做脏数据检查
	 */
	public Object deepCopy(Object value) {
		return value; // Address is immutable
	}

	/* 两个对象是否相等，使用了apache的common工具包来进行属性比对 */
	public boolean equals(Object x, Object y) {
		if (x == y)
			return true;
		if (x == null || y == null)
			return false;
		SimpleListType listStrType1 = (SimpleListType) x;
		SimpleListType listStrType2 = (SimpleListType) y;
		return new EqualsBuilder() // 使用EqualsBuilder类来方便地进行比对
				.append(listStrType1.toString(), listStrType2).isEquals();
	}

	/* 得到hash码 */

	public int hashCode(Object x) throws HibernateException {
		SimpleListType listStrType = (SimpleListType) x;
		return new HashCodeBuilder()// 使用HashCodeBuilder类来方便地进行比对
				.append(listStrType.toString()).toHashCode();
	}

	/* 当把AddressType类型数据写入二级缓存时，此方法被调用 */
	public Serializable disassemble(Object value) throws HibernateException {
		return null;
	}

	/* 当从二级缓存中读取AddressType类型数据时，此方法被调用 */
	public Object assemble(Serializable cached, Object owner) throws HibernateException {
		// TODO 自动生成方法存根
		return null;
	}

	public Object replace(Object original, Object target, Object owner) throws HibernateException {
		// TODO 自动生成方法存根
		return null;
	}

	public SimpleListType() {
		super();
	}

	public SimpleListType(String value) {
		if (StringUtils.isNotBlank(value)) {
			for (String val : StringUtils.split(value, ",")) {
				this.add(val) ;
			}
		}
	}

	/**
	 * @return 返回 sQL_TYPES。
	 */
	public static int[] getSQL_TYPES() {
		return SQL_TYPES;
	}

	/* 读取数据并组装成一个AddressType对象。names[]中的参数顺序依照映射文件中定义的顺序 */
	@Override
	public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor sessionImplementor, Object owner)
			throws HibernateException, SQLException {
		if (rs.wasNull())
			return null;
		String value = rs.getString(names[0]);
		SimpleListType list = new SimpleListType(value);
		return list;
	}

	/* 保存数据，index的顺序按照映射文件定义的顺序，从0开始。 */
	@Override
	public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor sessionImplementor)
			throws HibernateException, SQLException {
		SimpleListType list = (SimpleListType) value;
		if (value == null) {
			st.setNull(index, Types.VARCHAR);
		} else {
			st.setString(index, list.toString());
		}
		System.out.println("Data has been saved! ");
	}

}
